﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// Reviewed
#pragma once

#include "GcmpModelInterface.h"
#include "IElement.h"
#include <vector>

namespace gcmp
{
    class IDocument;
    class IFamilyType;
    class IInstanceType;
    class UniIdentity;

    struct GCMP_MODEL_INTERFACE_EXPORT FamilyThumbnailInfo
    {
        std::wstring CustomDataDirectory;             // 自定义数据文件路径
        std::wstring DefaultFileName;                 // 缩略图文件名
        std::wstring FullPath;                        // 缩略图完整路径
    };

    /// \brief  族接口类
    ///
    /// 族是一个包含通用属性（称作参数）集和相关图形表示的图元组。属于一个族的不同图元的部分
    /// 或者全部参数可能有不同的值，但是参数的集合是相同的。族中的这些变体称作族类型或者类型。
    /// 文档中，每一个族都有唯一的一个族配置对象存储族服务数据。
    /// \see  IFamilyConfigElement, IFamilyType
    class GCMP_MODEL_INTERFACE_EXPORT IFamily : public IElement
    {
        DEFINE_CAST_DERIVED(gcmp::IFamily, gcmp::IElement);
    public:
        /// \brief 通过族名字返回文档中的族对象
        /// 
        /// 非构件级协同级协同下，文档中不存在同名的族
        /// \param pDocument 文档指针
        /// \param familyName 族名字
        /// \return 如果存在，返回族对象，否则返回空指针
        static IFamily* GetFamilyByName(const IDocument* pDocument, const std::wstring& familyName);

        /// \brief 通过族名字返回文档中的所有的族对象
        /// 
        /// 构件级协同级协同下，文档可能存在同名的族
        /// \param pDocument 文档指针
        /// \param familyName 族名字
        /// \return 如果存在，返回族对象，否则返回空指针
        static std::vector<IFamily*> GetFamiliesByName(const IDocument* pDocument, const std::wstring& familyName);

        /// \brief 获得所有族
        /// 
        /// \param pDocument 文档指针
        /// \return 族集合
        static std::vector<IFamily*> GetAllFamilies(const IDocument* pDocument);

        /// \brief 返回给定名字的族类型
        ///
        /// 一个族中不存在同名的族类型
        /// \param familyTypeName 族类型名字
        /// \return 如果存在，返回族类型对象，否则返回空指针
        virtual const IFamilyType* GetFamilyTypeByName(const std::wstring& familyTypeName) const = 0;

        /// \brief 返回给定名字的族类型
        ///
        /// 一个族中不存在同名的族类型
        /// \param familyTypeName 族类型名字
        /// \return 如果存在，返回族类型对象，否则返回空指针
        virtual IFamilyType* GetFamilyTypeByName(const std::wstring& familyTypeName) = 0;

        /// \brief 返回族云端版本
        ///
        /// 通常用于构件级协同下
        /// \return 族版本号
        virtual Int32 GetFamilyVersionInCloud() const = 0;

        /// \brief 返回所有族类型
        ///
        /// \return 族类型数组
        virtual std::vector<const IFamilyType*> GetFamilyTypes() const = 0;

        /// \brief 返回给定类型名字对应的Instance类型
        ///
        /// \param typeName 类型名字
        /// \return 如果存在，返回实例对象类型，否则返回空指针
        virtual IInstanceType* GetInstanceTypeByName(const std::wstring& typeName) const = 0;

        /// \brief 返回给定类型名字对应的Instance类型数组
        ///
        /// 构件协同下，同一个typeName可能对应不同修改影响范围的IInstanceType对象，其中最多有一个是全局影响的。
        /// \param typeName 类型名字
        /// \return 如果存在，返回实例对象类型，否则返回空数组
        virtual std::vector<IInstanceType *> GetInstanceTypesByName(const std::wstring & typeName) const = 0;

        /// \brief 返回当前族所有的实例对象类型
        ///
        /// \return 实例对象类型数组，没有实例对象类型的话，数组为空
        virtual std::vector<IInstanceType*> GetInstanceTypes() const = 0;

        /// \brief 创建一个新实例对象类型，默认影响全局的相关IInstance
        ///
        /// \param familyTypeName 族类型名字
        /// \return 成功返回实例类型对象，否则返回空
        virtual IInstanceType* CreateInstanceType(const std::wstring& familyTypeName) = 0;

        /// \brief 创建一个新实例对象类型，可以指定是否影响全局的相关IInstance
        ///
        /// \param familyTypeName 族类型名字
        /// \param isGlobal 是否是全局影响。
        /// \return 成功返回实例类型对象，否则返回空
        virtual IInstanceType * CreateInstanceType(const std::wstring & familyTypeName, bool isGlobal) = 0;

        /// \brief 添加族类别
        ///
        /// \param IFamilyType 族类别
        /// \return 成功返回true，失败返回false
        virtual bool AddFamilyType(const IFamilyType* pFamilyType) = 0;

        /// \brief 删除族类别
        ///
        /// 如果InstanceType已经被某些Instance使用，不删除InstanceType和FamilyType，返回false
        /// \param IFamilyType 族类别
        /// \return 成功返回true，失败返回false
        virtual bool DeleteFamilyType(const std::wstring& familyTypeName) = 0;

        /// \brief 返回当前族是否为在位编辑族
        ///
        /// \return Inplace返回true，否则返回false
        virtual bool IsInplaceEditFamily() const = 0;

        /// \brief 设置当前族是否为在位编辑族(inplace)
        ///
        /// \param value true为在位编辑族，false为普通族
        /// \return 设置成功返回true，否则返回false
        virtual bool SetIsInplaceEditFamily(bool value) = 0;

        /// \brief 返回当前族的族服务UniIdentity
        ///
        /// \return 族服务UniIdentity
        virtual const UniIdentity& GetFamilyServiceUid() const = 0;

        /// \brief 返回族缩略图路径
        /// 
        /// \return 缩略图路径
        virtual std::wstring GetFamilyThumbnailPath() const = 0;

        /// \brief 获取族缩略图相关信息
        /// 
        /// \return 缩略图相关信息
        virtual const FamilyThumbnailInfo GetFamilyThumbnailInfo() const = 0;

        /// \brief 通过Uid查找属于此族的FamilyType(不可修改)
        ///
        /// \param typeUid 组类型的Uid
        /// \return 返回Uid相同的IFamliyType；如果没有返回nullptr
        virtual const IFamilyType* GetFamilyTypeByUid(const gcmp::UniIdentity& typeUid) const = 0;

        /// \brief 通过Uid查找属于此族的FamilyType(可修改)
        ///
        /// \param typeUid 组类型的Uid
        /// \return 返回Uid相同的IFamliyType；如果没有返回nullptr
        virtual IFamilyType* GetFamilyTypeByUidFW(const gcmp::UniIdentity& typeUid) = 0;

        /// \brief 通过Uid查找实例对象类型
        ///
        /// \param typeUid 组类型的Uid
        /// \return 返回Uid相同的IInstanceType；如果没有返回nullptr
        virtual const IInstanceType* GetInstanceTypeByUid(const gcmp::UniIdentity& typeUid) const = 0;

        /// \brief 获取构件缩放比例
        /// 
        /// \return 缩放比例
        /// \note 返回值应大于0，载入项目中缩放效果：缩放比例小于1.0为放大，例如值为0.1，则原构件在项目中放大10倍；1.0为原比例；缩放比例大于1.0为缩小，例如值为10，则原构件在项目中缩小10倍
        virtual double GetScale() const = 0;

        /// \brief 根据子构件实例类型获取对应的子构件类型
        /// 
        /// \param pSubInstanceType 子构件实例类型
        /// \return 子构件类型
        virtual const IFamilyType* GetSubFamilyTypeBySubInstanceType(const IInstanceType* pSubInstanceType) const = 0;

        /// \brief 根据子构件实例类型获取对应的子构件类型
        /// 
        /// \param pSubInstanceType 子构件实例类型
        /// \return 子构件类型
        virtual IFamilyType* GetSubFamilyTypeBySubInstanceType(IInstanceType* pSubInstanceType) = 0;

        /// \brief 根据子构件实例类型获取对应子构件的所有类型
        /// 
        /// \param pSubInstanceType 子构件实例类型
        /// \return 子构件类型数组
        virtual std::vector<const IFamilyType*> GetAllSubFamilyTypesBySubInstanceType(const IInstanceType* pSubInstanceType) const = 0;

        /// \brief 根据子构件实例类型获取对应子构件名称
        /// 
        /// \param pSubInstanceType 子构件实例类型
        /// \return 子构件名称
        virtual std::wstring GetSubFamilyNameBySubInstanceType(const IInstanceType* pSubInstanceType) const = 0;

        /// \brief 为子构件添加构件类型
        /// 
        /// \param subFamilyIdPath 子构件在主构件中的Id路径
        /// \param pFamilyType 添加的构件类型
        /// \return 添加成功返回true,添加失败返回false
        virtual bool AddSubFamilyType(const std::vector<Int64>& subFamilyIdPath, const IFamilyType* pFamilyType) = 0;

        /// \brief 创建一个子构件的新实例对象类型
        ///
        /// \param subFamilyIdPath 子构件在主构件中的Id路径
        /// \param familyTypeName 族类型名字
        /// \return 成功返回实例类型对象，否则返回空
        virtual IInstanceType* CreateSubInstanceType(const std::vector<Int64>& subFamilyIdPath, const std::wstring& familyTypeName) = 0;

        /// \brief 返回当前族所有的子构件对象类型
        ///
        /// \return 子构件对象类型数组，没有子构件对象类型的话，数组为空
        virtual std::vector<IInstanceType*> GetSubInstanceTypes() = 0;

    public:
        /// \brief 获取Implementation Uid
        ///
        /// \return UniIdentity 返回ImplementationUid
        static UniIdentity GetImplementationUid();
    };
}

